﻿using System;
using ParboiledSharp.parboiled.dataobjects;
using ParboiledSharp.parboiled.rules;

namespace ParboiledSharp.parboiled
{
    abstract class BaseParser
    {
        /// <summary>
        /// Custom user rule. Useful for creation semantic action
        /// </summary>
        protected Rule ACTION(Func<Context, bool> action)
        {
            return new rules.Action(action);
        }

        /// <summary>
        /// Custom user rule. Useful for creation semantic action
        /// </summary>
        protected Rule ACTION(System.Action<Context> action)
        {
            return new rules.Action(action);
        }

        /// <summary>
        /// Match for any character(only one character)
        /// </summary>
        protected Rule ANY()
        {
            return new Any();
        }

        /// <summary>
        /// Match if given input character is in [c1,c2] range
        /// </summary>
        protected Rule CHARRANGE(char c1, char c2)
        {
            return new CharRange(c1,c2);
        }

        /// <summary>
        /// Go throught the rules until one of the parameter rule returns TRUE
        /// </summary>
        protected Rule FIRST(params object[] rules)
        {
            return new FirstOf(rules);
        }

        /// <summary>
        /// Returns TRUE only if all parameter rules return FALSE
        /// </summary>
        protected Rule NONE(params object[] rules)
        {
            return new None(rules);
        }

        /// <summary>
        /// Returns TRUE only if all parameter rules return TRUE
        /// </summary>
        protected Rule SEQUENCE(params object[] rules)
        {
            return new Sequence(rules);
        }

        /// <summary>
        /// Returns TRUE only if all parameter rules return TRUE.
        /// Also in case of successful executing of all rules, makes "push" of all matched string
        /// </summary>
        protected Rule SEQUENCEPUSH(params object[] rules)
        {
            return new SequencePush(rules);
        }

        /// <summary>
        /// Returns TRUE if parameter rule return FALSE
        /// </summary>
        protected Rule NOT(object rule)
        {
            return new Not(rule);
        }

        /// <summary>
        /// Repeats execution of the parameter rule, until it returns FALSE.
        /// If at least one itertion returns TRUE, ONEORMORE rule returns TRUE
        /// </summary>
        protected Rule ONEORMORE(object rule)
        {
            return new OneOrMore(rule);
        }

        protected Rule ONEORMORE()
        {
            return new OneOrMore();
        }

        /// <summary>
        /// Repeats execution of the parameter rule, until it returns FALSE.
        /// Always return TRUE
        /// </summary>
        protected Rule ZEROORMORE(object rule)
        {
            return new ZeroOrMore(rule);
        }

        /// <summary>
        /// Tries to execute parameter rule
        /// Always return TRUE
        /// </summary>
        protected Rule OPTIONAL(object rule)
        {
            return new Optional(rule);
        }

        /// <summary>
        /// Tries to execute parameter rule, returns the result
        /// Restore input and value stack in previous position
        /// </summary>
        protected Rule TEST(object rule)
        {
            return new Test(rule);
        }

        /// <summary>
        /// Tries to execute parameter rule, returns the inverted result
        /// Restore input and value stack in previous position
        /// </summary>
        protected Rule TESTNOT(object rule)
        {
            return new TestNot(rule);
        }

        /// <summary>
        /// Push last matched string to the top of the value stack
        /// </summary>
// ReSharper disable InconsistentNaming
        protected Rule PUSH()
// ReSharper restore InconsistentNaming
        {
            return new PushMatch();
        }

        /// <summary>
        /// Tries to match parameter string and the input. Case sensitive
        /// </summary>
        protected Rule STRING(string match)
        {
            return new StringRule(match, false);
        }

        /// <summary>
        /// Tries to match parameter string and the input. Case insensitive
        /// </summary>
        protected Rule STRINGIGNORECASE(string match)
        {
            return new StringRule(match, true);
        }

        /// <summary>
        /// Print the message to the stdout.
        /// </summary>
        protected Rule PRINT(string message)
        {
            return new DebugPrintAction(message, false);
        }

        /// <summary>
        /// Print the message with new line to the stdout.
        /// </summary>
        protected Rule PRINTLN(string message)
        {
            return new DebugPrintAction(message, true);
        }
    }
}
